/**
 * 
 */
package cz.cvut.fit.crhonjar.mi.paa.thames;

import java.util.ArrayList;
import java.util.List;

import cz.cvut.fit.crhonjar.mi.paa.thames.exception.ExceptionCode;
import cz.cvut.fit.crhonjar.mi.paa.thames.exception.ThamesException;

/**
 * @author Jarec
 * 
 */
public class Configuration {

	private Integer depth;
	private final List<Item> items;

	private final List<Boolean> presence;
	private Integer price;

	private Integer weight;

	/**
	 * @param c
	 */
	public Configuration(final Configuration c) {
		if (c == null) {
			throw new IllegalArgumentException(
					"Configuration constructor called with NULL Configuration as parameter!");
		}
		this.items = c.getItems();
		this.presence = new ArrayList<Boolean>(c.getPresence());
		this.price = c.price;
		this.weight = c.weight;
		this.depth = c.depth;
	}

	/**
	 * @param items
	 */
	public Configuration(final List<Item> items) {
		if (items == null) {
			throw new IllegalArgumentException(
					"Configuration constructor called with NULL items as parametr!");
		}
		this.items = items;
		this.presence = new ArrayList<Boolean>();
		for (int i = 0; i < items.size(); i++) {
			this.presence.add(Boolean.FALSE);
		}
		this.price = 0;
		this.weight = 0;
		this.depth = 0;
	}

	/**
	 * @param items
	 * @param state
	 */
	public Configuration(final List<Item> items, final State state) {
		this.items = items;
		this.presence = new ArrayList<Boolean>();
		this.price = state.getPrice();
		this.weight = state.getWeigth();
		this.depth = -1;
		for (int i = 0; i < items.size(); i++) {
			if (state.getItems().contains(items.get(i))) {
				this.presence.add(true);
			} else {
				this.presence.add(false);
			}

		}
	}

	/**
	 * @param index
	 */
	public void addItem(final Integer index) {
		if (index == null) {
			throw new IllegalArgumentException(
					"Cannot add item witgh NULL index!");
		}
		if (index >= this.items.size()) {
			throw new IllegalArgumentException("Item index out of bouns!");
		}
		if (this.presence.get(index) == true) {
			throw new IllegalArgumentException("Item is already present!");
		}
		this.presence.set(index, Boolean.TRUE);
		this.price += this.items.get(index).getPrice();
		this.weight += this.items.get(index).getWeight();
	}

	/**
	 * @return the depth
	 */
	public Integer getDepth() {
		return this.depth;
	}

	/**
	 * @return the items
	 */
	public List<Item> getItems() {
		return this.items;
	}

	/**
	 * @return the presence
	 */
	public List<Boolean> getPresence() {
		return this.presence;
	}

	/**
	 * @return the price
	 */
	public Integer getPrice() {
		return this.price;
	}

	/**
	 * @return the weight
	 */
	public Integer getWeight() {
		return this.weight;
	}

	/**
	 * increases depth of configuration
	 * 
	 * @throws ThamesException
	 */
	public void increaseDepth() throws ThamesException {
		if (this.depth >= this.items.size()) {
			throw new ThamesException(
					ExceptionCode.INCORRECT_CONFIGURATION_DEPTH,
					"Maximum depth reached!");
		}
		this.depth++;
	}

	/**
	 * @param weight
	 */
	public void increaseWeight(final Integer weight) {
		this.weight += weight;
	}

	/**
	 * @param price
	 */
	public void incresePrice(final Integer price) {
		this.price += price;
	}

	/**
	 * @return
	 */
	public Integer priceLeft() {
		int p = 0;
		for (int i = this.depth - 1; i < this.getItems().size(); i++) {
			p += this.getItems().get(i).getPrice();
		}
		return p;
	}

}